//
//  BBFilterConfigController.m
//  BBTouch
//
//  Created by ben smith on 28/09/08.
//  This file is part of BBTouch.
//
//  BBTouch is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.

//  BBTouch is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Lesser General Public License for more details.

//  You should have received a copy of the GNU Lesser General Public License
//  along with BBTouch.  If not, see <http://www.gnu.org/licenses/>.
// 
//  Copyright 2008 Ben Britten Smith ben@benbritten.com .
//

#import "BBFilterConfigController.h"
#import "BBMeshController.h"
#import "BBConfigurationController.h"


@implementation BBFilterConfigController

BBFilterConfigController * sharedFilterConfigController;

@synthesize bgStorage;

-(void)awakeFromNib
{
	sharedFilterConfigController = self;
	[myWindow setDelegate:self];
	
}

+(BBFilterConfigController*)sharedFilterConfigController
{
	return sharedFilterConfigController;
}

-(IBAction)openWindow:(id)sender
{
	[myWindow makeKeyAndOrderFront:self];	
	NSRect roi = [[BBMeshController sharedMeshController] regionOfInterest];
	
	CvRect cvROI = cvRect(NSMinX(roi), NSMinY(roi), NSWidth(roi), NSHeight(roi));
	cvSetImageROI(srcIpl, cvROI);
	cvSetImageROI(bgIpl, cvROI);
	cvSetImageROI(bgsubIpl, cvROI);
	cvSetImageROI(finalIpl, cvROI);
	cvSetImageROI(bufferIpl, cvROI);
	cvSetImageROI(hpassIpl, cvROI);
	[self startListening];
}

- (void)windowWillClose:(NSNotification *)notification
{
	[self stopListening];
}

-(IBAction)closeWindow:(id)sender;
{
	[myWindow performClose:self];
}


-(void)startListening
{
	// Initialization code here.
	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(imageUpdate:) name:@"BBRawVideoImageChange" object:nil];
}

-(void)stopListening
{
	// Initialization code here.
	[[NSNotificationCenter defaultCenter] removeObserver:self];
}

-(void)setBackgroundImage:(NSImage*)anImage
{

	if (self.bgStorage == nil) {
		// setup all my ipl images
		NSSize imageSize = [anImage size];
		srcIpl = cvCreateImage(cvSize(imageSize.width, imageSize.height), IPL_DEPTH_8U, 1);
		bgIpl = cvCreateImage(cvSize(imageSize.width, imageSize.height), IPL_DEPTH_8U, 1);
		
		bgsubIpl = cvCreateImage(cvSize(imageSize.width, imageSize.height), IPL_DEPTH_8U, 1);
		hpassIpl = cvCreateImage(cvSize(imageSize.width, imageSize.height), IPL_DEPTH_8U, 1);
		finalIpl = cvCreateImage(cvSize(imageSize.width, imageSize.height), IPL_DEPTH_8U, 1);
		bufferIpl = cvCreateImage(cvSize(imageSize.width, imageSize.height), IPL_DEPTH_8U, 1);		
	}
	self.bgStorage = anImage;
	[bgView setImage:self.bgStorage];
	NSBitmapImageRep * bgRep = [[self.bgStorage representations] objectAtIndex:0];
	
	cvSetData(bgIpl, [bgRep bitmapData], [bgRep bytesPerRow]);
}



-(void)imageUpdate:(NSNotification*)note
{
	// update all my images
	NSImage * src = [note object];
	[sourceView setImage:src];
//	[bgView setImage:self.bgStorage];
	NSBitmapImageRep * srcRep = [[src representations] objectAtIndex:0];
	
	cvSetData(srcIpl, [srcRep bitmapData], [srcRep bytesPerRow]);
	// ok here is the big kludgy suck:
	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
	
	[self subtractBackground];
	[self higpassFilter];
	[self noiseFilter];
	[self threshold];
	
	[pool release];
}

-(void)subtractBackground
{
	// removes the bg from the src and stores it in the bgsubIpl
	// then loads that into an image and sets the image view
	NSBitmapImageRep * bitRep = [self emptyBitmapRep];
	cvSetData(bgsubIpl, [bitRep bitmapData], [bitRep bytesPerRow]);

	if ([BBConfigurationController boolForSettingKey:@"BBInvertBlobCheck"]) {
		cvSub(bgIpl, srcIpl, bgsubIpl,0);				
	}	else {
		cvSub(srcIpl, bgIpl, bgsubIpl,0);		
	}

	NSImage *filterImg = [[NSImage alloc] initWithSize:[bitRep size]];
	[filterImg addRepresentation:bitRep];
	[bgSubtractionView setImage:filterImg];
	[filterImg release];
}


-(void)higpassFilter
{
	// removes the bg from the src and stores it in the bgsubIpl
	// then loads that into an image and sets the image view
	NSBitmapImageRep * bitRep = [self emptyBitmapRep];
	cvSetData(hpassIpl, [bitRep bitmapData], [bitRep bytesPerRow]);

	NSInteger highpassValue  = [BBConfigurationController intForSettingKey:@"BBHighPassKernelSize"];	
	if (highpassValue <= 2)  {
		highpassValue = 3;		
		[BBConfigurationController setObject:[NSNumber numberWithInt:highpassValue] forSettingKey:@"BBHighPassKernelSize"];
	}
	if ((highpassValue % 2) == 0) {
		highpassValue -= 1; 
		[BBConfigurationController setObject:[NSNumber numberWithInt:highpassValue] forSettingKey:@"BBHighPassKernelSize"];		
	}
	
	
	cvSmooth(bgsubIpl, hpassIpl, CV_BLUR, highpassValue, highpassValue, 0, 0);
	//cvAbsDiff(source, buffer, buffer);
	cvSub(bgsubIpl, hpassIpl, hpassIpl,0);
		
	NSImage *filterImg = [[NSImage alloc] initWithSize:[bitRep size]];
	[filterImg addRepresentation:bitRep];
	[highPassView setImage:filterImg];
	[filterImg release];
}

-(void)noiseFilter
{
	// removes the bg from the src and stores it in the bgsubIpl
	// then loads that into an image and sets the image view
	NSBitmapImageRep * bitRep = [self emptyBitmapRep];
	cvSetData(bufferIpl, [bitRep bitmapData], [bitRep bytesPerRow]);
	
	NSInteger noiseValue  = [BBConfigurationController intForSettingKey:@"BBNoiseKernelSize"];	
	if (noiseValue <= 2)  {
		noiseValue = 3;		
		[BBConfigurationController setObject:[NSNumber numberWithInt:noiseValue] forSettingKey:@"BBNoiseKernelSize"];
	}
	if ((noiseValue % 2) == 0) {
		noiseValue -= 1; 
		[BBConfigurationController setObject:[NSNumber numberWithInt:noiseValue] forSettingKey:@"BBNoiseKernelSize"];		
	}
	
	cvSmooth(hpassIpl, bufferIpl, CV_BLUR, noiseValue, noiseValue, 0, 0);
		
	NSImage *filterImg = [[NSImage alloc] initWithSize:[bitRep size]];
	[filterImg addRepresentation:bitRep];
	[noiseView setImage:filterImg];
	[filterImg release];
}

-(void)threshold
{
	// removes the bg from the src and stores it in the bgsubIpl
	// then loads that into an image and sets the image view
	NSBitmapImageRep * bitRep = [self emptyBitmapRep];
	
	cvSetData(finalIpl, [bitRep bitmapData], [bitRep bytesPerRow]);
	
	NSInteger threshSize  = [BBConfigurationController intForSettingKey:@"BBThresholdKernelSize"];	
	NSInteger threshoffset  = [BBConfigurationController intForSettingKey:@"BBThresholdMedianOffset"];	
	
	if (threshSize <= 2)  {
		threshSize = 3;		
		[BBConfigurationController setObject:[NSNumber numberWithInt:threshSize] forSettingKey:@"BBThresholdKernelSize"];
	}
	if ((threshSize % 2) == 0) {
		threshSize -= 1; 
		[BBConfigurationController setObject:[NSNumber numberWithInt:threshSize] forSettingKey:@"BBThresholdKernelSize"];		
	}
	
	cvAdaptiveThreshold(bufferIpl, finalIpl, 200, CV_THRESH_BINARY, CV_ADAPTIVE_THRESH_MEAN_C, threshSize, threshoffset);

	NSImage *filterImg = [[NSImage alloc] initWithSize:[bitRep size]];
	
	[filterImg addRepresentation:bitRep];
	[thresholdView setImage:filterImg];
	
	[filterImg release];
}




-(NSBitmapImageRep*)emptyBitmapRep
{
	if (self.bgStorage == nil) return nil;
	return [[[NSBitmapImageRep alloc]
	 initWithBitmapDataPlanes:NULL
	 pixelsWide:[bgStorage size].width
	 pixelsHigh:[bgStorage size].height
	 bitsPerSample:8
	 samplesPerPixel:1
	 hasAlpha:NO
	 isPlanar:YES
	 colorSpaceName:NSDeviceWhiteColorSpace
	 bytesPerRow:0
	 bitsPerPixel:0] autorelease];
}


@end
